import time
import random
from . import models
from django.db.models import F
from django.conf import settings
from rest_framework import serializers

from .utils import check_phone
from utils.private.md5 import uid
from utils.centent.sms import send_sms_single
from utils.centent.cos import create_bucket

from django_redis import get_redis_connection
from django.forms.models import model_to_dict


class LoginModelSerializer(serializers.ModelSerializer):
    """登录序列化器"""
    code = serializers.CharField(write_only=True)
    phone = serializers.CharField()
    nickName = serializers.CharField()

    class Meta:
        model = models.UserInfo
        fields = ['phone', 'token', 'code', 'nickName', 'id']
        extra_kwargs = {
            'token': {'read_only': True},
            'id': {'read_only': True},
        }

    def validate(self, attrs):
        # 校验手机号
        phone = attrs.get('phone')
        nickName = attrs.get('nickName')
        if not phone or not check_phone(phone):
            raise serializers.ValidationError('手机号有误')
        # 校验验证码
        # 去rdis中取,校验是否存在
        # 与前端传送过来的code进行对比
        h_code = attrs.get('code')
        if not h_code:
            raise serializers.ValidationError('验证码不能为空')
        conn = get_redis_connection('sms_code')
        r_code = conn.get('sms_code_%s' % phone)
        if not r_code:
            raise serializers.ValidationError('验证码过期')
        if r_code.decode('utf-8') != h_code:
            raise serializers.ValidationError('验证码错误')
        # 通过手机号进行查询，没有，进行用户创建，以传入的phone为字段内容
        user_obj, bool = models.UserInfo.objects.get_or_create(phone=phone)  # 以phone进行查询，后面的default是没有创建的
        # get_...两个参数，用户对象，bool(存在返回Fals，新创建的返回True)
        user_obj.token = uid(phone)
        # 根据第二个参数判断，如果是第一次登录的话，创建桶
        if bool:
            Bucket = '{}-{}-1305448189'.format(phone, str(int(time.time())))
            # 创建桶
            create_bucket(Bucket=Bucket)
            user_obj.bucket = Bucket
            user_obj.nickName = nickName
            # user_obj.save()
        user_obj.save()
        # print(user_obj.token)
        self.context['phone'] = user_obj.phone
        self.context['token'] = user_obj.token
        self.context['bucket'] = user_obj.bucket
        self.context['region'] = user_obj.region
        self.context['id'] = user_obj.id

        # 对用户的token进行生成/更新，
        # 返回
        return attrs


class SmsCodeSerializer(serializers.Serializer):
    """短信发送序列化器"""
    phone = serializers.CharField(max_length=11, min_length=11, write_only=True)
    tpl = serializers.CharField()

    def validate(self, validate_data):
        phone = validate_data.get('phone')
        # 进行短信模板id校验
        tpl = validate_data.get('tpl')
        # tpl
        tpl_id = self._get_tpl_id(tpl=tpl)
        # 进行手机号格式校验
        ret = check_phone(phone=phone)
        if ret:
            code = self._set_code(phone=phone)
            # 都通过发验证码
            self._send_sms(phone=phone, tpl_id=tpl_id, code=code)
            return validate_data
        raise serializers.ValidationError('手机号验证失败')

    def _get_tpl_id(self, tpl):
        """
        短信模板id的获取
        :param tpl: 前端传过来的，login/register/...
        :return:
        """
        if not tpl:
            raise serializers.ValidationError('模板缺失')
        tpl_id = settings.TENCENT_SMS_TEMPLATES.get(tpl)
        if not tpl_id:
            raise serializers.ValidationError('模板错误')
        return tpl_id

    def _set_code(self, phone):
        """
        生成验证码存放redis
        :param phone: 手机号
        :return:
        """
        # 生成code
        code = random.randrange(1000, 9999)
        print(code)
        # 保存redis
        conn = get_redis_connection('sms_code')
        pipe = conn.pipeline()  # 创建管道
        pipe.multi()  # 开启批量操作  （事务，）
        #  # 后端倒计时校验 查看redis是否有，有抛异常
        init_code = conn.get('init_code_%s' % phone)
        if init_code:
            raise serializers.ValidationError('一分钟只能发一次')
        # 保存正常验证码
        pipe.set('sms_code_%s' % phone, code, ex=60 * 60 * 24 * 14)
        # 保存倒计时码
        pipe.set('init_code_%s' % phone, code, ex=60)
        pipe.execute()  # 批量执行了
        return code

    def _send_sms(self, phone, tpl_id, code):
        """
        celery 异步消息队列发送短信
        :param phone: 手机号
        :param tpl_id: tpl_id 前端传，根据settings里面配置的
        :param code: 验证码
        :return:
        """
        # todo celery异步消息队列
        send_sms_single(phone, tpl_id, [code, ])


class TopicModelSerializer(serializers.ModelSerializer):
    """话题序列化器"""

    class Meta:
        model = models.Topic
        fields = ['id', 'name', 'people_num']


class MediaModelSerializer(serializers.ModelSerializer):
    """嵌套"""

    class Meta:
        model = models.Media
        fields = ['cosUrl', 'cosETag', 'cos_media_name']


class ReleaseModelSerializer(serializers.ModelSerializer):
    cos_data = MediaModelSerializer(many=True, write_only=True)
    topic_id = serializers.CharField(write_only=True)
    userinfo_id = serializers.CharField(write_only=True)

    class Meta:
        model = models.Release
        fields = ['position', 'content', 'topic_id', 'userinfo_id', 'cos_data']

    def create(self, validated_data):
        """
        {'position': '大河南', 'content': '真美', 'topic': <Topic: Topic object (5)>, 'userinfo': <UserInfo: UserInfo object (2)>}
        """
        # print(cos_data)
        # print(validated_data)
        # print(validated_data.get('topic_id'))
        # print(validated_data.get('userinfo_id'))
        position = validated_data.get('position', '该用户没有提供位置信息')
        user_id = validated_data.get("userinfo_id", None)
        content = validated_data.get('content', None)
        topic_id = validated_data.get('topic_id', None)
        # 进行校验
        position, user_id, content, topic_id = self._is_legitimate(position, user_id, content, topic_id)
        # 创建发布表
        release_obj = self._create_release(position, user_id, content, topic_id)

        """
        [OrderedDict([('cosUrl', 'd.com/303.png'), ('cosETag', '2497fd5b672c2e07'), ('cos_media_name', '088356.png')]), OrderedDict([('cosUrl', 'd.com/303.png'), ('cosETag', '2497fd5b672c2e07'), ('cos_media_name', '088356.png')])]

        """

        cos_data = validated_data.pop("cos_data")
        # 如果没有cos_data(是一个列表) 说明没有发布图片/视频，就不用创建
        if cos_data:
            # 循环cos_data进行创建media表
            self._creat_media(release_obj=release_obj, cos_data=cos_data)
        # 给话题增加人数 #todo 无法相加？未找到原因
        # 利用F 给话题增加人数

        # models.Release.objects.filter(topic_id=topic_id).update(topic__people_num=F('topic__people_num') + 1)
        # a = models.Release.objects.filter(topic_id=topic_id).values('topic__people_num')
        # print(release_obj.topic.people_num)
        # print(a)
        # 查询本表进行操作
        topic_obj = models.Topic.objects.filter(id=topic_id).first()
        # print('1', topic_obj.people_num)
        topic_obj.people_num += 1
        topic_obj.save()
        # print('2', topic_obj.people_num)
        return release_obj

    def _create_release(self, position, user_id, content, topic_id):
        """创建发布表"""
        release_obj = models.Release.objects.create(
            **{
                "position": position,
                "content": content,
                "userinfo_id": user_id,
                "topic_id": topic_id
            }
        )
        return release_obj

    def _creat_media(self, release_obj, cos_data):
        """创建图片/视频"""
        for item in cos_data:
            # 进行拼接即可
            cosUrl = item.get('cosUrl')
            tail = cosUrl.split('/')[-1].split('.')[-1][-1]
            if tail == 'g':
                name = '图片'
                type = 2
            else:
                name = '视频'
                type = 3
            cosETag = item.get('cosETag')
            cos_media_name = item.get('cos_media_name')
            models.Media.objects.create(
                **{
                    'name': name,
                    'type': type,
                    'cosUrl': cosUrl,
                    'release': release_obj,
                    'cosETag': cosETag,
                    'cos_media_name': cos_media_name
                }
            )

    def _is_legitimate(self, position, user_id, content, topic_id):
        """进行校验"""
        if not user_id:
            raise serializers.ValidationError('用户不存在')
        if not content:
            raise serializers.ValidationError('内容不能为空')
        if not topic_id:
            raise serializers.ValidationError('必须选一个话题哦')
        return position, user_id, content, topic_id


class IndexDataModelSerializer(serializers.ModelSerializer):
    """首页返回的数据"""
    # topic = serializers.CharField(source='topic.name')
    #
    # nickName = serializers.CharField(source='userinfo.nickName')
    topic = serializers.SerializerMethodField()
    userinfo = serializers.SerializerMethodField()
    create_time = serializers.DateTimeField(format='%Y-%m-%d')

    class Meta:
        model = models.Release
        fields = [
            'id', 'position', 'content', 'release_up', 'create_time',
            'cover_msg_url', 'topic', 'userinfo',
        ]

    def get_topic(self, obj):
        return model_to_dict(obj.topic, fields=['id', 'name'])

    def get_userinfo(self, obj):
        return model_to_dict(obj.userinfo, fields=['id', 'nickName', 'avatar'])


class IndexDetailDataModelSerializer(serializers.ModelSerializer):
    """首页的详情页返回的数据"""
    create_time = serializers.DateTimeField(format='%Y-%m-%d')
    topic = serializers.SerializerMethodField()
    userinfo = serializers.SerializerMethodField()
    msg_url = serializers.SerializerMethodField()
    watcher = serializers.SerializerMethodField()
    comment = serializers.SerializerMethodField()
    is_favor = serializers.SerializerMethodField()

    class Meta:
        model = models.Release
        fields = [
            'id', 'position', 'is_favor', 'content', 'release_up', 'watch_num', 'release_num', 'create_time',
            'topic', 'userinfo', 'msg_url', 'watcher', 'comment',
        ]

    def get_topic(self, obj):
        """返回话题格式"""
        return model_to_dict(obj.topic, fields=['id', 'name'])

    def get_userinfo(self, obj):
        """返回用户格式"""
        return model_to_dict(obj.userinfo, fields=['id', 'nickName', 'avatar'])

    def get_msg_url(self, obj):
        """返回图片格式"""
        return [model_to_dict(item, fields=['id', 'cosUrl']) for item in obj.media.all()]

    def get_watcher(self, obj):
        """浏览记录的格式"""
        watch_queryset = models.WatchNum.objects.filter(new=obj).order_by('-id')
        watch_content = watch_queryset.count()
        watch_query = watch_queryset[0:10]
        # print(watch_query)
        # print([model_to_dict(item.userinfo, fields=['id', 'nickName', 'avatar']) for item in watch_query])
        # for item in watch_query:
        #     # print(item.userinfo.nickName)
        #     print(item.userinfo.id)
        #     print(item.userinfo.avatar)
        # print('1', watch_query)
        context = {
            'count': watch_content,
            'result': [model_to_dict(item.userinfo, fields=['id', 'nickName', 'avatar']) for item in watch_query]
        }
        return context

        # 测试前端传送过来一个列表

    def get_comment(self, obj):
        """评论格式的处理"""
        # 一级所有&二级的最后一个
        # 获取所有的一级评论
        first_queryset = models.Comment.objects.filter(is_show=True, is_delete=False, depth=1, new=obj).order_by(
            '-id').values(
            'id', 'comment', 'depth', 'create_time', 'comment_up',
            'userinfo__nickName', 'userinfo__avatar',

        )
        # 获取所有的二级评论
        # ??? 怎么把userinfo给添加进去---用values
        # 获取所有一级评论下的二级评论 ，然后以replay_id进行分组，因为replay是关联父id的字段，有相同的，然后取出最大的id
        first_id_list = [item['id'] for item in first_queryset]
        from django.db.models import Max
        # 每条二级评论的id的最大值
        # <QuerySet [{'reply_id': 7, 'max_id': 15}, {'reply_id': 8, 'max_id': 11}, {'reply_id': 9, 'max_id': 12}]>
        result = models.Comment.objects.filter(is_show=True, is_delete=False, depth=2,
                                               reply_id__in=first_id_list).values('reply_id').annotate(
            max_id=Max('id'))
        tow_queryset_id = [item['max_id'] for item in result]
        tow_queryset = models.Comment.objects.filter(id__in=tow_queryset_id).values(
            'id', 'comment', 'create_time', 'comment_up', 'depth',
            'userinfo__nickName', 'userinfo__avatar',  # 发这个评论的名称
            'reply_id',
            'reply__userinfo__nickName',  # 回复的是哪个一级

        )
        # print(tow_queryset)
        # 对二级评论与一级评论进行拼接
        # 构造一个有序字典
        from collections import OrderedDict
        first_dict = OrderedDict()

        for item in first_queryset:
            item['create_time'] = item['create_time'].strftime('%Y-%m-%d')
            first_dict[item['id']] = item

        for node in tow_queryset:
            if node['reply_id'] in first_dict:
                node['create_time'] = node['create_time'].strftime('%Y-%m-%d')
                first_dict[node['reply_id']]['children'] = [node, ]

        return first_dict.values()

    def get_is_favor(self, obj):
        # 1. 未登录--False
        user_obj = self.context['request'].user
        if not user_obj:
            return False
        # 2. 未点赞
        exist = models.ReleaseUp.objects.filter(userinfo=user_obj, new=obj).exists()
        return exist


class CommentModelSerializer(serializers.ModelSerializer):
    """评论渲染"""
    userinfo__nickName = serializers.CharField(source='userinfo.nickName')
    userinfo__avatar = serializers.CharField(source='userinfo.avatar')
    create_time = serializers.DateTimeField(format='%Y-%m-%d')
    reply_id = serializers.CharField(source='reply.id')  # 父级的id
    reply__userinfo__nickName = serializers.CharField(source='reply.userinfo.nickName')

    class Meta:
        model = models.Comment
        fields = [
            'id', 'create_time', 'comment', 'depth', 'userinfo__nickName', 'comment_up', 'userinfo__avatar', 'reply_id',
            'reply__userinfo__nickName'
        ]


class PostCommentModelSerializer(serializers.ModelSerializer):
    """评论提交"""
    userinfo__nickName = serializers.CharField(source='userinfo.nickName', read_only=True)
    userinfo__avatar = serializers.CharField(source='userinfo.avatar', read_only=True)
    create_time = serializers.DateTimeField(format='%Y-%m-%d', read_only=True)
    reply_id = serializers.CharField(source='reply.id', read_only=True)  # 父级的id
    reply__userinfo__nickName = serializers.CharField(source='reply.userinfo.nickName', read_only=True)
    comment_up = serializers.CharField(read_only=True)

    class Meta:
        model = models.Comment
        fields = ['id', 'comment', 'new', 'reply', 'depth', 'root', 'comment_up',
                  'userinfo__nickName', 'userinfo__avatar', 'create_time',
                  'reply_id', 'reply__userinfo__nickName',
                  ]


class ThumbsModelSerializer(serializers.ModelSerializer):
    """点赞"""

    class Meta:
        model = models.ReleaseUp
        fields = ['new']


"""
class T1(serializers.Serializer):
    name2 = serializers.CharField()
    name3 = serializers.CharField()


class T2(serializers.ModelSerializer):
    t1 = T1(many=True)  # 这样可以传列表 卧槽牛逼！！！

    class Meta:
        model = models.Release
        fields = ['content', 't1']

    def validate(self, attrs):
        print(attrs)
        # OrderedDict([('content', 'aa'), ('t1', [OrderedDict([('name2', '1'), ('name3', '3')]), OrderedDict([('name2', '1'), ('name3', '3')]), OrderedDict([('name2', '1'), ('name3', '3')])])])

    def create(self, validated_data):
        print(validated_data)

    # OrderedDict([('content', 'aa'), ('t1', [OrderedDict([('name2', '1'), ('name3', '3')]), OrderedDict([('name2', '1'), ('name3', '3')]), OrderedDict([('name2', '1'), ('name3', '3')])])])

    '''
    {
    "content":"aa",
    "t1":[
        {"name2":"1","name3":"3"},
        {"name2":"1","name3":"3"},
        {"name2":"1","name3":"3"}
        
    ]
}
    '''
"""


class AuctionModelSerializer(serializers.ModelSerializer):
    """拍卖列表序列化器"""
    status = serializers.CharField(source='get_status_display')
    auction_item = serializers.SerializerMethodField()
    preview_start_time = serializers.DateTimeField(format='%Y-%m-%d %H:%M', read_only=True)
    preview_end_time = serializers.DateTimeField(format='%Y-%m-%d %H:%M', read_only=True)
    auction_start_time = serializers.DateTimeField(format='%Y-%m-%d %H:%M', read_only=True)
    auction_end_time = serializers.DateTimeField(format='%Y-%m-%d %H:%M', read_only=True)
    # 重写字段，不然返回对象的存储路径
    cover = serializers.CharField()

    class Meta:
        model = models.Auction
        fields = [
            'id', 'status', 'title', 'cover', 'preview_start_time',
            'preview_end_time', 'auction_start_time', 'auction_end_time',
            'look_count', 'auction_item'
        ]

    def get_auction_item(self, obj):
        # 查询拍卖品
        query = models.AuctionItem.objects.filter(auction=obj)
        item_list = []
        for item in query[0:10]:
            item_list.append({'id': item.id, 'cover': item.cover.name})
        dic = {
            'count': query.count(),
            # 'result': [model_to_dict(item, fields=['id', 'cover']) for item in query[0:10]]
            'result': item_list
        }
        return dic


class AuctionItem(serializers.ModelSerializer):
    """拍卖场详细--拍品 序列化器嵌套"""
    is_deposit = serializers.SerializerMethodField()
    # 重写字段，不然返回对象的存储路径
    cover = serializers.CharField()

    class Meta:
        model = models.AuctionItem
        fields = ['id', 'uid', 'title', 'cover', 'is_deposit',
                  'start_price', 'reserve_price', 'highest_price',
                  'unit',
                  ]

    # 是否缴纳单品保证金
    # 是否缴纳全场/单品保证金
    def get_is_deposit(self, obj):
        # 判断是否登录
        user = self.context['request'].user
        if not user:
            return False
        # 如果是全场，单品为null
        # 判断是否交了保障金，True/False
        exist = models.DepositRecord.objects.filter(user=user, item=obj, status=2).exists()
        return exist


class AuctionDetailModelSerializer(serializers.ModelSerializer):
    """拍卖场详细"""
    status = serializers.CharField(source='get_status_display')
    auction_item = serializers.SerializerMethodField()
    preview_start_time = serializers.DateTimeField(format='%Y-%m-%d %H:%M', read_only=True)
    preview_end_time = serializers.DateTimeField(format='%Y-%m-%d %H:%M', read_only=True)
    auction_start_time = serializers.DateTimeField(format='%Y-%m-%d %H:%M', read_only=True)
    auction_end_time = serializers.DateTimeField(format='%Y-%m-%d %H:%M', read_only=True)
    is_deposit = serializers.SerializerMethodField()
    item_count = serializers.SerializerMethodField()
    # 重写字段，不然返回对象的存储路径
    cover = serializers.CharField()

    class Meta:
        model = models.Auction
        fields = [
            'id', 'status', 'title', 'cover', 'is_deposit', 'preview_start_time',
            'preview_end_time', 'auction_start_time', 'auction_end_time',
            'look_count', 'item_count', 'auction_item'
        ]

    def get_auction_item(self, obj):
        # 查询拍卖品
        item_list = models.AuctionItem.objects.filter(auction=obj)
        ser = AuctionItem(instance=item_list, many=True, context=self.context)
        return ser.data

    # 是否缴纳全场/单品保证金
    def get_is_deposit(self, obj):
        # 判断是否登录
        user = self.context['request'].user
        if not user:
            return False
        # 如果是全场，单品为null
        # 判断是否交了保障金，True/False
        exist = models.DepositRecord.objects.filter(user=user, item__isnull=True, status=2).exists()
        return exist

    def get_item_count(self, obj):
        # obj--Auction 当前的modes表对象
        return models.AuctionItem.objects.filter(auction=obj).count()


class AuctionItemDetailModelSerializer(serializers.ModelSerializer):
    """单个商品详细序列化器"""
    images = serializers.SerializerMethodField()
    # 重写字段，不然返回对象的存储路径
    cover = serializers.CharField()

    class Meta:
        model = models.AuctionItem
        fields = ['id', 'uid', 'title', 'cover', 'start_price',
                  'deal_price', 'reserve_price', 'highest_price',
                  'deposit', 'unit', 'look_count', 'images'

                  ]

    def get_images(self, obj):
        """获取当前商品的图片"""

        item_img = models.AuctionItemImage.objects.filter(item=obj, carousel=False)
        item_list = []
        for item in item_img:
            item_list.append({'id': item.id, 'img': item.img.name})
        # return [model_to_dict(item, fields=['id', 'img']) for item in item_img]
        return item_list


class AuctionDepositModelSerializer(serializers.ModelSerializer):
    deposits = serializers.SerializerMethodField()
    balance = serializers.SerializerMethodField()
    # 重写字段，不然返回对象的存储路径
    cover = serializers.CharField()

    class Meta:
        model = models.AuctionItem
        fields = ['id', 'title', 'cover',
                  'reserve_price', 'highest_price', 'deposits',
                  ]

    def get_balance(self, obj):
        balance = self.context['request'].user.balance

        return balance

    def get_deposits(self, obj):
        # 查看是全场保证金
        # 查看单品保障金
        result = {
            'selected': 1,
            'data_list': [
                {'id': 1, 'price': obj.deposit, 'text': '全场保障金'},
                {'id': 2, 'price': obj.auction.deposit, 'text': '全场保障金'},

            ]
        }
        return result


class BidRecordModelSerializer(serializers.ModelSerializer):
    status = serializers.CharField(source='get_status_display', read_only=True)
    username = serializers.CharField(source='user.nickName', read_only=True)
    id = serializers.CharField(read_only=True)

    class Meta:
        model = models.BidRecord
        fields = ['id', 'status', 'item', 'price', 'username']

    def validate_item(self, attrs):
        # item传的就是id,但被反射成立对象
        exist = models.AuctionItem.objects.filter(id=attrs.id, status=3).exists()
        if not exist:
            raise serializers.ValidationError('当前商品未开始竞拍，请等待！')

    def validate_price(self, attrs):
        # 底价/最高价/加价幅度 item---这里是id
        item_id = self.initial_data.get('item')
        auction_obj = models.AuctionItem.objects.filter(id=item_id).first()
        if int(attrs) < auction_obj.start_price:
            raise serializers.ValidationError('价格必须比低价高！')
        # 1. 去出价表，查出最新最大的一条价格记录
        # 2. 当前价格与查询的价格进行比较，
        from django.db.models import Max
        # 获取前端传送改过来的item---initial_data# 进行聚合，求出最大值，{'max_price':1200}
        old_price = models.BidRecord.objects.filter(status=1, item_id=item_id).aggregate(max_price=Max('price'))[
            'max_price']
        # 4. 如果比查询出来的小，异常
        if int(attrs) < old_price:
            raise serializers.ValidationError('出价不能比当前价格小！')
        # 3. 如果不是加价幅度，异常

        if int(attrs) % auction_obj.unit != 0:
            raise serializers.ValidationError('请按照加价幅度出价！')
        return attrs


#################### 优惠卷 ##################
import datetime


class CouponModelSerializer(serializers.ModelSerializer):
    title = serializers.CharField(source='title.title')
    coupon_type_formula = serializers.CharField(source='coupon_type.formula')
    coupon_type = serializers.CharField(source='coupon_type.get_coupon_type_display')
    start_time = serializers.DateTimeField(format='%Y-%m-%d %H:%M:%S')
    end_time = serializers.DateTimeField(format='%Y-%m-%d')
    cover = serializers.CharField()

    class Meta:
        model = models.CouponStrength
        fields = [
            'id', 'title', 'coupon_type', 'get_ranges_display',
            'get_status_display', 'cover', 'use_limit', 'start_time',
            'end_time', 'total_count', 'surplus_count', 'coupon_type_formula'
        ]


class CouponApplyModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.UserCoupon
        fields = [
            'strength',
        ]

    def validate_strength(self, attrs):
        # 1. 要求前端传送过来，当前优惠卷的id
        # 2. 后端校验
        # 2.1 是否开始/过期/领过/存在/登录
        now = datetime.datetime.now()
        # 是否开始 / 过期 / 剩余
        # print(attrs.id)
        coupon_obj = models.CouponStrength.objects.filter(id=attrs.id, status=2, start_time__lte=now, end_time__gte=now,
                                                          surplus_count__gte=1, is_delete=False, is_show=True).first()
        self.context['coupon_obj'] = coupon_obj
        if not coupon_obj:
            raise serializers.ValidationError('优惠劵不存在')
        # 3. 领过/存在/登录
        user_obj = self.context['request'].user
        if not user_obj:
            raise serializers.ValidationError('请登录')
        user_coupon_obj = models.UserCoupon.objects.filter(user=user_obj, strength=attrs)
        if user_coupon_obj:
            raise serializers.ValidationError('只能领取一次')
        # 3. 校验成功，当前用户领取，给用户优惠劵表添加一条记录   /事务加锁，一次只能一个领取
        self.context['end_time'] = coupon_obj.end_time
        return attrs

    def create(self, validated_data):

        user = self.context['request'].user
        strength = validated_data.get('strength')
        # print(strength) # 对象
        user_coupon = models.UserCoupon.objects.create(
            user=user,
            strength=strength
        )
        user_coupon.end_time = self.context['coupon_obj'].end_time
        user_coupon.save()
        return user_coupon


class CouponUserSerializer(serializers.ModelSerializer):
    """用户优惠劵"""
    title = serializers.CharField(source='strength.title.title', read_only=True)
    end_time = serializers.CharField(source='strength.end_time', read_only=True)
    status_type = serializers.CharField(source='strength.get_status_display', read_only=True)
    status = serializers.CharField(read_only=True)
    strength_coupon_type = serializers.CharField(source='strength.coupon_type.get_coupon_type_display', read_only=True)
    strength_formula = serializers.CharField(source='strength.coupon_type.formula', read_only=True)
    strength_cover = serializers.CharField(source='strength.cover', read_only=True)

    class Meta:
        model = models.UserCoupon
        fields = ['id', 'title', 'end_time', 'status', 'status_type', 'strength_coupon_type', 'strength_formula',
                  'strength_cover']


class OrderSerializer(serializers.ModelSerializer):
    """订单返回序列化器"""
    create_time = serializers.DateTimeField(format='%Y-%m-%d %H:%M:%S', read_only=True)
    title = serializers.CharField(source='auction_item.title', read_only=True)
    status = serializers.CharField(read_only=True)
    cover = serializers.CharField(source='auction_item.cover', read_only=True)

    class Meta:
        model = models.Order
        fields = ['id', 'title', 'price', 'create_time', 'status', 'cover']


class OrderDetailSerializer(serializers.ModelSerializer):
    """订单详细返回序列化器"""
    create_time = serializers.DateTimeField(format='%Y-%m-%d %H:%M:%S', read_only=True)
    title = serializers.CharField(source='auction_item.title', read_only=True)
    status = serializers.CharField(read_only=True)
    cover = serializers.CharField(source='auction_item.cover', read_only=True)
    uid = serializers.CharField(source='auction_item.uid', read_only=True)
    coupon = serializers.SerializerMethodField()

    class Meta:
        model = models.Order
        fields = ['id', 'title', 'price', 'create_time', 'status', 'cover', 'uid', 'coupon']

    def get_coupon(self, obj):
        coupon_query = models.UserCoupon.objects.filter(user=self.context['request'].user, status=1)
        # 获取当前优惠劵
        coupon_dic = []
        for item in coupon_query:
            coupon_dic.append(
                {
                    'text': item.strength.title.title,
                    'coupon_type': item.strength.coupon_type.get_coupon_type_display(),
                    'formula': item.strength.coupon_type.formula
                }
            )
        return coupon_dic
